package com.rtsapp.server.common;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import com.rtsapp.server.logger.Logger;

import java.nio.ByteOrder;
import java.util.Date;


public class ByteBuffer implements IByteBuffer {

    private static final Logger logger = com.rtsapp.server.logger.LoggerFactory.getLogger(ByteBuffer.class);

    private ByteBuf buffer;

    public ByteBuffer() {
        this.buffer = Unpooled.buffer();
    }

    public ByteBuffer(int initialCapacity) {
        this.buffer = Unpooled.buffer(initialCapacity);
    }

    public ByteBuffer(ByteBuf buffer) {
        this.buffer = buffer;
    }

    public ByteBuffer(byte[] bytes) {
        this.buffer = Unpooled.wrappedBuffer(bytes);
    }

	/*
    public static byte[] getByteArrFromUTF(String str) {
		int strlen = str.length();
		int utflen = 0;
		int c, count = 0;
		for (int i = 0; i < strlen; i++) {
			c = str.charAt(i);
			if ((c >= 0x0001) && (c <= 0x007F)) {
				utflen++;
			} else if (c > 0x07FF) {
				utflen += 3;
			} else {
				utflen += 2;
			}
		}
		byte[] bytearr = new byte[utflen];
		int i = 0;
		for (i = 0; i < strlen; i++) {
			c = str.charAt(i);
			if (!((c >= 0x0001) && (c <= 0x007F))) {
				break;
			}
			bytearr[count++] = (byte) c;
		}
		for (; i < strlen; i++) {
			c = str.charAt(i);
			if ((c >= 0x0001) && (c <= 0x007F)) {
				bytearr[count++] = (byte) c;

			} else if (c > 0x07FF) {
				bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
				bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
				bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
			} else {
				bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
				bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
			}
		}
		return bytearr;
	}
	*/


    /**
     * 字节序
     *
     * @return
     */
    public ByteOrder order() {
        return buffer.order();
    }


    /**
     * 返回读的index
     *
     * @return
     */
    public int readerIndex() {
        return buffer.readerIndex();
    }

    /**
     * 设置读的index
     *
     * @param readerIndex
     */
    public void readerIndex(int readerIndex) {
        buffer.readerIndex(readerIndex);
    }

    /**
     * 写的位置
     *
     * @return
     */
    public int writeIndex() {
        return buffer.writerIndex();
    }

    /**
     * 设置写的位置
     *
     * @param writeIndex
     */
    public void writeIndex(int writeIndex) {
        buffer.writerIndex(writeIndex);
    }

    /**
     * 重置读写指针
     */
    public void reset() {
        readerIndex(0);
        writeIndex(0);
    }

    /**
     * 返回ByteBuffer中所有写入的字节数组
     * <p>Method of {@code array} are not safe for use by multiple threads.</p>
     */
    public byte[] array() {

        int length = buffer.writerIndex();
        byte[] bytes = new byte[length];
        buffer.getBytes(0, bytes, 0, length);
        return bytes;
    }

    /**
     * 将ByteBuffer的数据转换在bytes中返回
     *
     * @return
     */
    public byte[] toBytes() {
        return array();
    }


    public int capacity() {
        return buffer.capacity();
    }

    /**
     * 返回可读的字节数
     *
     * @return
     */
    public int readableBytes() {
        return buffer.readableBytes();
    }

    /**
     * 设置指定位置的int值，不改变读写index
     *
     * @param index
     * @param value
     */
    public void setInt(int index, int value) {
        buffer.setInt(index, value);
    }

    /**
     * 获取指定位置的int值，不改变读写索引
     *
     * @param index
     */
    public int getInt(int index) {
        return buffer.getInt(index);
    }

    public boolean readBool() {
        return buffer.readBoolean();
    }

    public byte readByte() {
        return buffer.readByte();
    }

    public short readShort() {
        return buffer.readShort();
    }

    public int readInt() {
        return buffer.readInt();
    }

    public long readLong() {
        return buffer.readLong();
    }

    public Date readDate() {
        return new Date(buffer.readLong());
    }

    public float readFloat() {
        return buffer.readFloat();
    }

    public double readDouble() {
        return buffer.readDouble();
    }

    public String readUTF8() {

        int times = 0;
        int utflen = buffer.readShort();
        if (utflen == -1) {
            return null;
        }
        byte[] bytearr = new byte[utflen];
        char[] chararr = null;

        buffer.readBytes(bytearr, 0, utflen);
        if (utflen > bytearr.length) {
            return null;
        }
        chararr = new char[utflen];

        int c, char2, char3;
        int count = 0;
        int chararr_count = 0;

        while (count < utflen) {
            times++;
            if (times > utflen) {
                logger.error("读取UTF异常1...{}, {}", times, utflen);
                return "";
            }
            c = (int) bytearr[count] & 0xff;
            if (c > 127) {
                break;
            }
            count++;
            chararr[chararr_count++] = (char) c;
        }
        times = 0;
        while (count < utflen) {
            times++;
            if (times > utflen) {
                logger.error("读取UTF异常3...{}, {}", times, utflen);
                return "";
            }
            c = (int) bytearr[count] & 0xff;
            switch (c >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7: /* 0xxxxxxx */
                    count++;
                    chararr[chararr_count++] = (char) c;
                    break;
                case 12:
                case 13: /* 110x xxxx 10xx xxxx */
                    count += 2;
                    char2 = (int) bytearr[count - 1];
                    chararr[chararr_count++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
                    break;
                case 14: /* 1110 xxxx 10xx xxxx 10xx xxxx */
                    count += 3;
                    char2 = (int) bytearr[count - 2];
                    char3 = (int) bytearr[count - 1];
                    chararr[chararr_count++] = (char) (((c & 0x0F) << 12)
                            | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
                    break;
                default:
                    logger.error("读取UTF异常2...");
                    return "";
            }
        }
        return new String(chararr, 0, chararr_count);
        // return null;
    }

    public void writeBool(boolean value) {
        buffer.writeBoolean(value);
    }

    public void writeByte(byte value) {
        buffer.writeByte(value);
    }

    public void writeByteArray(byte[] value) {
        buffer.writeShort(value.length);
        buffer.writeBytes(value);
    }

    public void writeBytesDirect(byte[] value) {
        buffer.writeBytes(value);
    }


    public byte[] readByteArray() {
        short len = buffer.readShort();
        byte[] bytes = new byte[len];
        buffer.readBytes(bytes, 0, bytes.length);
        return bytes;
    }

    public void writeShort(short value) {
        buffer.writeShort(value);
    }

    public void writeInt(int value) {
        buffer.writeInt(value);
    }

    public void writeLong(long value) {
        buffer.writeLong(value);
    }

    public void writeDate(Date value) {
        buffer.writeLong(value.getTime());
    }

    public void writeFloat(float value) {
        buffer.writeFloat(value);
    }

    public void writeDouble(double value) {
        buffer.writeDouble(value);
    }

    public void writeUTF8(String value) {
        if (value == null) {
            value = "";
        }
        byte[] bytes = IByteBuffer.getByteArrFromUTF(value);
        buffer.writeShort((short) bytes.length);
        buffer.writeBytes(bytes);
    }

}
